﻿using System;

namespace Cpu6502.Opcodes
{
    /// <summary>
    /// LDA #AA - LDA Immediate Mode
    /// Loads value directly into accumalator
    /// </summary>
    public class LDA_I : Opcode
    {
        public LDA_I()
        {
            this.CpuCycles = 2;
            this.AddressType = CPU.AddressType.Immediate;
        }

        public override void Execute()
        {
            CPU.Registers.A = (byte)base.Argument;

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (CPU.Registers.A == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((CPU.Registers.A << 7) & 1) != 0);      
        }
    }

    /// <summary>
    /// LDA $AAAA - LDA Absolute Mode
    /// Loads Value from memory into accumulator
    /// </summary>
    public class LDA_A : Opcode
    {
        public LDA_A()
        {
            this.CpuCycles = 4;
            this.AddressType = CPU.AddressType.Absolute;
        }

        public override void Execute()
        {
            CPU.Registers.A = CPU.Memory[base.Argument];

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (CPU.Registers.A == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((CPU.Registers.A << 7) & 1) != 0);
        }
    }
  
    /// <summary>
    /// LDA ($AA, X) - LDA IndexedIndirect mode
    /// Loads Value from memory into accumulator
    /// </summary>
    public class LDA_Indexed_Indirect : Opcode
    {
        public LDA_Indexed_Indirect()
        {
            this.CpuCycles = 6;
            this.AddressType = CPU.AddressType.IndexedIndirect;
        }

        public override void Execute()
        {                        
            CPU.Registers.A = 
                CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument,
                    CPU.AddressType.IndexedIndirect)
                ];

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (CPU.Registers.A == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((CPU.Registers.A << 7) & 1) != 0);
        }
    }

    /// <summary>
    /// LDA ($AA),Y - LDA IndirectIndexed Mode
    /// Loads Value from memory into accumulator
    /// </summary>
    public class LDA_Indirect_Indexed : Opcode
    {
        public LDA_Indirect_Indexed()
        {
            this.CpuCycles = 5;
            this.AddressType = CPU.AddressType.IndirectIndexed;
        }

        public override void Execute()
        {                       
            CPU.Registers.A = 
                CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument,
                    CPU.AddressType.IndirectIndexed)
                ];

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (CPU.Registers.A == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((CPU.Registers.A << 7) & 1) != 0);
        }
    }

    /// <summary>
    /// LDA $AAAA, X - LDA Absolute X Mode
    /// Loads Value from memory into accumulator
    /// </summary>
    public class LDA_A_X : Opcode
    {
        public LDA_A_X()
        {
            this.CpuCycles = 4;
            this.AddressType = CPU.AddressType.AbsoluteIndexedX;
        }

        public override void Execute()
        {
            CPU.Registers.A = 
                CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument,
                    CPU.AddressType.AbsoluteIndexedX)
                ];


            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (CPU.Registers.A == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((CPU.Registers.A << 7) & 1) != 0);
        }
    }

    /// <summary>
    /// LDA $AAAA, Y - LDA Absolute Y Mode
    /// Loads Value from memory into accumulator
    /// </summary>
    public class LDA_A_Y : Opcode
    {
        public LDA_A_Y()
        {
            this.CpuCycles = 4;
            this.AddressType = CPU.AddressType.AbsoluteIndexedY;
        }

        public override void Execute()
        {
            CPU.Registers.A = 
                CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument,
                    CPU.AddressType.AbsoluteIndexedY)
                ];

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (CPU.Registers.A == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((CPU.Registers.A << 7) & 1) != 0);
        }
    }
    
    /// <summary>
    /// LDA $AA - LDA ZeroPage Mode
    /// Loads Value from memory into accumulator
    /// </summary>
    public class LDA_ZP : Opcode
    {
        public LDA_ZP()
        {
            this.CpuCycles = 3;
            this.AddressType = CPU.AddressType.ZeroPage;
        }

        public override void Execute()
        {            
            CPU.Registers.A = 
                CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument,
                    CPU.AddressType.ZeroPage)
                ];

           
            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (CPU.Registers.A == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((CPU.Registers.A << 7) & 1) != 0);
        }
    }

    /// <summary>
    /// LDA $AA, X - LDA ZeroPage X Mode
    /// Loads Value from memory into accumulator
    /// </summary>
    public class LDA_ZP_X : Opcode
    {
        public LDA_ZP_X()
        {
            this.CpuCycles = 3;
            this.AddressType = CPU.AddressType.ZeroPageIndexedX;
        }

        public override void Execute()
        {           
            CPU.Registers.A = 
                CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument,
                    CPU.AddressType.ZeroPageIndexedX)
                ];

            // Set the Zero Flag if the data is 0
            CPU.Registers.P.Z = (CPU.Registers.A == 0);

            // If bit 7 of accumulator is set, then Negative flag must be set.
            CPU.Registers.P.N = (((CPU.Registers.A << 7) & 1) != 0);
        }
    }  
}
